import { Context } from 'koa';
import User from '../model/User';
import { Model } from 'sequelize-typescript';
import { APIError } from '../plugin/restful';
import { sign } from '../plugin/jwt';
import { getUser } from '../service/user';
import { generateParamsError, md5WithSecret } from '../utils';

const PARAMS_VALIDATE_FAIL_CODE = 'user: params_validate_fail';
const WRONG_PASSWORD = new APIError('user: wrong_password', '密码错误');

// GET /users
// Description: 获取用户列表
export const getList = async (ctx: Context) => {
  const users = <User[]> (await User.findAll());
  ctx.body = users;
};

// GET /token
// Query: account, password
// Description: 用户登录
export const getToken = async (ctx: Context) => {
  ctx.checkQuery('account').notEmpty();
  ctx.checkQuery('password').len(4, 20);
  if (ctx.errors) throw generateParamsError(PARAMS_VALIDATE_FAIL_CODE, ctx.errors);
  const { account, password } = ctx.request.query;
  const user = await getUser({ account });
  if (user.password !== md5WithSecret(password)) throw WRONG_PASSWORD;
  const token = await sign({ account });
  ctx.body = { token };
};

// GET /user/:id
// Description: 获取单个用户信息
export const getOne = async (ctx: Context) => {
  ctx.checkParams('id').isNumeric();
  if (ctx.errors) throw generateParamsError(PARAMS_VALIDATE_FAIL_CODE, ctx.errors);
  const { id } = ctx.params;
  const user = await getUser({ id });
  ctx.body = user;
};

// POST /user
// Body: account, password
// Description: 用户注册
export const create = async (ctx: Context) => {
  ctx.checkBody('account').notEmpty();
  ctx.checkBody('password').len(4, 20);
  if (ctx.errors) throw generateParamsError(PARAMS_VALIDATE_FAIL_CODE, ctx.errors);
  const { account, password } = ctx.request.body;
  const user = <User> await User.create({
    account, password: md5WithSecret(password)
  });
  ctx.body = user.id;
};

// PUT /user/:id
// Body: password
// Description: 更改密码
export const update = async (ctx: Context) => {
  ctx.checkBody('password').len(4, 20);
  if (ctx.errors) throw generateParamsError(PARAMS_VALIDATE_FAIL_CODE, ctx.errors);
  const { id } = ctx.params;
  const { password } = ctx.request.body;
  const user = await getUser({ id });
  user.password = md5WithSecret(password);
  await user.save();
  ctx.body = user.id;
};

// DELETE /user/:id
// Description: 删除用户
export const del = async (ctx: Context) => {
  ctx.checkParams('id').isNumeric();
  if (ctx.errors) throw generateParamsError(PARAMS_VALIDATE_FAIL_CODE, ctx.errors);
  const { id } = ctx.params;
  const user = await getUser({ id });
  await user.destroy();
  ctx.body = '';
};
